
package laya.semi.service;

import java.util.*;
import java.util.regex.*;
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.*;

import laya.*;
import laya.util.*;
import laya.xml.sax.*;

import org.apache.log4j.*;

public class GenericServiceLayerConfig extends DefaultHandler
{
	private static Logger log = Logger.getLogger(GenericServiceLayerConfig.class);

	public static final String TAG_ROOT = LayaGlobals.LAYA_NAMESPACE + ":" + "Services";
	public static final String TAG_SERVICE = LayaGlobals.LAYA_NAMESPACE + ":" + "Service";
	public static final String TAG_SERVICEMAPPING = LayaGlobals.LAYA_NAMESPACE + ":" + "ServiceMapping";
	public static final String TAG_SERVICEHANDLER = LayaGlobals.LAYA_NAMESPACE + ":" + "ServiceHandler";
	public static final String TAG_SERVICEDESCRIPTION = LayaGlobals.LAYA_NAMESPACE + ":" + "ServiceDescription";
	
	public static final int STATE_READY = 0;
	public static final int STATE_START = 1;
	public static final int STATE_START_SERVICE = 2;
	public static final int STATE_START_SERVICEMAPPING = 3;
	public static final int STATE_GET_SERVICEMAPPING = 4;
	public static final int STATE_START_SERVICEHANDLER = 5;
	public static final int STATE_GET_SERVICEHANDLER = 6;
	public static final int STATE_START_SERVICEDESCRIPTION = 7;
	public static final int STATE_GET_SERVICEDESCRIPTION = 8;
	public static final int STATE_END_SERVICEDESCRIPTION = 9;
	public static final int STATE_END_SERVICE = 10;
	public static final int STATE_END = 11;
	
	private int m_nStep = STATE_READY;
	private List m_oServiceLayerList = null;
	private Hashtable m_oClassHandlerTab = null;
	private Hashtable m_oMappingHandlerTab = null;
	private StringBuffer m_oContentBuffer = null;
	
	private String m_oServiceMapping = null;

	public IServiceHandler getServiceHandler(String oSvcId)
	{
		int nServiceMappingCount = m_oServiceLayerList.size();
		
		for (int i = 0; i < nServiceMappingCount; ++i)
		{
			GSLConfigBean oConfigBean = (GSLConfigBean)m_oServiceLayerList.get(i);
			if (oConfigBean.matches(oSvcId))
			{
				return oConfigBean.getServiceHandler();
			}
		}
		
		return null;
	}
	
	public void startDocument()
		throws SAXException
	{
		// log.debug("startDocument()");
		m_oServiceLayerList = new Vector();
		m_oClassHandlerTab = new Hashtable();
		m_oMappingHandlerTab = new Hashtable();
		m_nStep = STATE_START;
	}
	
	public void startElement(String uri, String localName, String qName, Attributes attributes)
		throws SAXException
	{
		// log.debug("startElement(" + uri + ", " + localName + ", " + qName + ")");
		switch(m_nStep)
		{
			case STATE_START:
			{
				if (!TAG_ROOT.equals(qName))
				{
					throw new SAXParseException(1004, m_nStep, qName, TAG_ROOT);
				}
				
				m_nStep = STATE_START_SERVICE;
				break;
			}
			case STATE_START_SERVICE:
			{
				if (!TAG_SERVICE.equals(qName))
				{
					throw new SAXParseException(1004, m_nStep, qName, TAG_SERVICE);
				}
				
				m_nStep = STATE_START_SERVICEMAPPING;
				break;
			}
			case STATE_START_SERVICEMAPPING:
			{
				if (!TAG_SERVICEMAPPING.equals(qName))
				{
					throw new SAXParseException(1004, m_nStep, qName, TAG_SERVICEMAPPING);
				}
				
				m_oContentBuffer = new StringBuffer();
				m_nStep = STATE_GET_SERVICEMAPPING;
				break;
			}
			case STATE_START_SERVICEHANDLER:
			{
				if (!TAG_SERVICEHANDLER.equals(qName))
				{
					throw new SAXParseException(1004, m_nStep, qName, TAG_SERVICEHANDLER);
				}
				
				m_oContentBuffer = new StringBuffer();
				m_nStep = STATE_GET_SERVICEHANDLER;
				break;
			}
			case STATE_START_SERVICEDESCRIPTION:
			{
				if (!TAG_SERVICEDESCRIPTION.equals(qName))
				{
					throw new SAXParseException(1004, m_nStep, qName, TAG_SERVICEDESCRIPTION);
				}
				
				m_oContentBuffer = new StringBuffer();
				m_nStep = STATE_GET_SERVICEDESCRIPTION;
				break;
			}
			default:
			{
				throw new SAXParseException(1002, m_nStep, qName);
			}
		}
	}
	
	public void characters(char[] ch, int start, int length)
		throws SAXException
	{
		//log.debug("characters()");
		
		switch(m_nStep)
		{
			case STATE_GET_SERVICEMAPPING:
			case STATE_GET_SERVICEHANDLER:
			//case STATE_GET_SERVICEDESCRIPTION:
			{
				m_oContentBuffer.append(ch, start, length);
				break;
			}
		}
	}
	
	public void endElement(String uri, String localName, String qName)
		throws SAXException
	{
		// log.debug("endElement(" + uri + ", " + localName + ", " + qName + ")");
		switch(m_nStep)
		{
			case STATE_GET_SERVICEMAPPING:
			{
				m_oServiceMapping = m_oContentBuffer.toString().trim();
				if (null != m_oMappingHandlerTab.get(m_oServiceMapping))
				{
					throw new SAXParseException(1211, m_oServiceMapping);
				}
				
				m_nStep = STATE_START_SERVICEHANDLER;
				break;
			}
			case STATE_GET_SERVICEHANDLER:
			{
				String oHandlerClassName = m_oContentBuffer.toString().trim();
				IServiceHandler oHandler = (IServiceHandler)m_oClassHandlerTab.get(oHandlerClassName);
				
				if (null == oHandler)
				{
					try
					{
						oHandler = (IServiceHandler)Class.forName(oHandlerClassName).newInstance();
					}
					catch(Exception e)
					{
						log.warn(MessageResource.getDefaultInstance().getMessage("laya.exception.1212", new String[] {oHandlerClassName}), e);
						throw new SAXParseException(1212, oHandlerClassName);
					}
					
					m_oClassHandlerTab.put(oHandlerClassName, oHandler);
				}
				
				m_oMappingHandlerTab.put(m_oServiceMapping, oHandler);
				m_oServiceLayerList.add(new GSLConfigBean(oHandler, m_oServiceMapping));
				
				m_nStep = STATE_START_SERVICEDESCRIPTION;
				break;
			}
			case STATE_GET_SERVICEDESCRIPTION:
			{
				m_nStep = STATE_END_SERVICEDESCRIPTION;
				break;
			}
			case STATE_END_SERVICEDESCRIPTION:
			case STATE_START_SERVICEDESCRIPTION:
			{
				m_nStep = STATE_START_SERVICE;
				break;
			}
			case STATE_START_SERVICE:
			{
				m_nStep = STATE_END;
				break;
			}
			default:
			{
				throw new SAXParseException(1003, m_nStep, qName);
			}
		}
	}
	
	public void endDocument()
		throws SAXException
	{
		// log.debug("endDocument()");
		
		switch(m_nStep)
		{
			case STATE_START:
			{
				log.warn(MessageResource.getDefaultInstance().getMessage("laya.info.ServiceHandlerConfigEmpty"));
				break;
			}
			case STATE_END:
			{
				log.info(MessageResource.getDefaultInstance().getMessage("laya.info.ServiceHandlerConfigLoadOk"));
				break;
			}
			default:
			{
				throw new SAXParseException(1001, m_nStep);
			}
		}
	}
}

class GSLConfigBean
{
	private static Logger log = Logger.getLogger(GSLConfigBean.class);
	
	private IServiceHandler m_oSvcHandler = null;
	private Pattern m_oMappingPattern = null;
	
	public GSLConfigBean(IServiceHandler oSvcHandler, String oMappingExpr)
		throws SAXParseException
	{
		m_oSvcHandler = oSvcHandler;
		
		// log.debug("before translate: " + oMappingExpr);
		if (!oMappingExpr.matches("[[0-9]|[\\.]|[A-Z]|[a-z]|[_]|[\\-]|[\\*]|[\\?]]*"))
		{
			throw new SAXParseException(1213, oMappingExpr);
		}
		oMappingExpr = oMappingExpr.replaceAll("\\.", "\\\\.");
		oMappingExpr = oMappingExpr.replaceAll("\\*", "\\.*");
		oMappingExpr = oMappingExpr.replaceAll("\\?", ".");
		// log.debug("after translate: " + oMappingExpr);
		
		m_oMappingPattern = Pattern.compile(oMappingExpr);
	}
	
	public IServiceHandler getServiceHandler()
	{
		return m_oSvcHandler;
	}
	
	public Pattern getMappingPattern()
	{
		return m_oMappingPattern;
	}
	
	public boolean matches(String oSvcId)
	{
		Matcher m = m_oMappingPattern.matcher(oSvcId);
		return m.matches();
	}
}
